#!usr/bin/bash python
#-*- coding=utf8 -*-

import os
import sys
import urllib2
import base64
import time
import httplib
import socket
from lxml import etree
from urllib2 import HTTPError
'''
	@args    : USB:net:power or USB:net or USB
	@funcrion: get the usb_net&power box offline and then online;
	@pre-work: box be reachable & local service starts; 
	@notes: power2 is unuseable;
'''

'''
   when occure exception, sleep except_sleep seconds and go on trying..
'''
exception_sleep = 0 

module_index = []
USB_NET_PW_INFO = {
					"module":["USB", "network", "power"],
					"actions":[["closeusb", "openusb"],
							  ["closenet", "opennet"],
							  ["closepower01", "openpower01"]],
				    "iptype":["USBIP", "USBIP", "powerIP"],
					"boxip":["10.100.14.33", "10.100.14.33", "10.100.14.34"]}

					
#"powerstate":"FE 01 01 01 A0 5C 00 00", 
#only use power1 and ensure its open state
state_dict = {"alloff":"FE 01 01 00 A0 5C 00 00",
			  "1on":"FE 01 01 01 A0 5C 00 00",
			  "2on":"FE 01 01 02 A0 5C 00 00",
			  "allon":"FE 01 01 03 A0 5C 00 00"}
ACTION_RESULT_INFO = {
					"powerstate":state_dict,
					"USBState":state_dict,
					"netState":state_dict,
					"opennet":"FE 05 00 01 FF 00 C9 F5",
					"closenet":"FE 05 00 01 00 00 88 05",
					"openpower01":"FE 05 00 00 FF 00 98 35",
					"closepower01":"FE 05 00 00 00 00 D9 C5",
					"openusb":"FE 05 00 00 FF 00 98 35",
					"closeusb":"FE 05 00 00 00 00 D9 C5",
					}
					
ags = sys.argv[1].split(":")
for ag in ags:
	if ag.strip() in USB_NET_PW_INFO["module"]:
		module_index.append(USB_NET_PW_INFO["module"].index(ag.strip()))
	else:
		print ag.strip()

if len(module_index) <> len(ags):
	print "unrecgnized parameter.\n"
	#return

def ip_is_online(ip):
	import subprocess
	#rev = subprocess.Popen("ping -n 2 %s" % ip)
	rev = os.system("ping -n 2 %s" % ip)
	return True if rev == 0 else False

def sendHTTPRequest(method, url, host, port='8080', content=None, password=None, ifnonematch=None, retries=3, pause = 0):
#     import ssl
#     ssl._create_default_https_context = ssl._create_unverified_context
    returnDict = {}
    headers = {}
    assert retries >= 0, 'retries must be greater than or equal to 0'
    headers['Connection'] = 'Keep-Alive'
    if None != password:
        authString = 'Basic %s' % base64.b64encode(password)
        headers['Authorization'] = authString
    if None != ifnonematch:
        headers['If-None-Match'] = ifnonematch
    headers['Content-Type'] = 'text/xml'
    if content != None:
        headers['Content-Length'] = str(len(content))
    retries = retries or 1
    for attempt in range(0, retries):
        try:
            http_conn = httplib.HTTPConnection(host, port, strict=True, timeout=30)
            http_conn.request(method, url, content, headers)
            time.sleep(pause)
            httpResponse = http_conn.getresponse()
            returnDict['httpstatus'] = httpResponse.status
            returnDict['httpreason'] = httpResponse.reason
            returnDict['httpheader'] = httpResponse.msg
            if method == 'GET' and httpResponse.status == 200:
                responseContent = httpResponse.read()
            else:
                responseContent = None
            returnDict['content'] = responseContent or None
            break;
        except (httplib.HTTPException, socket.error), info:
            if attempt < retries - 1:
                print('%s: Error connecting to device: %s. Trying again in 10 seconds...' % (__name__, info), 3)
            else:
                print('%s: Error connecting to device: %s.' % (__name__, info), 3)
        finally:
            http_conn.close()
    return returnDict

def get_printer_info(ip):
    res = sendHTTPRequest('GET', '/DevMgmt/ProductConfigDyn.xml', host=ip)
    return __get_fwNo_printerName_serNO(res['content'])

def __get_fwNo_printerName_serNO(aStr):
    tree = etree.fromstring(aStr).getroottree().getroot()
    bor = lambda i : i.text and i.text or list(i.iterchildren())[0].text
    return [bor(c) for c in [b for b in [a for a in tree.iterchildren() if 'ProductInformation' in a.tag][0].iterchildren()
                             if 'Version' in b.tag or 'MakeAndModelFamily' in b.tag or 'SerialNumber' in b.tag]]

def netBoxState(reCode, cur_boxip, module="netBox"):
	
	time.sleep(10)
	urllib_opener = urllib2.build_opener()  
	urllib_opener.addheaders.append(('Cookie', 'jeesite.session.id=5666dc26a4b246f1b64ab1619da7c03f;Hm_lvt_82116c626a8d504a5c0675073362ef6f=1479692411,1481614969,1481764178,1481788301; token=493c7803bd33b8b05c823b9f87d62e1f; Hm_lpvt_82116c626a8d504a5c0675073362ef6f=1481790761; loginName=thinkgem;password=admin'))  
	#f = opener.open("http://example.com/")  
	if module=="netBox":
		url1="http://localhost:8080/jeesite/test/USB/USBState?USBIP=%s" % cur_boxip
	elif module=="pwrBox":
		url1="http://localhost:8080/jeesite/test/power/powerstate?powerIP=%s" % cur_boxip
	req = urllib2.Request(url1)  
	response = urllib_opener.open(req)  
	retdata = response.read()
	status = response.getcode()
	print "state:",status,",",retdata
	if status == 200:
		if retdata.split()[3] in reCode:
			return True
	return False

def act_of_module_is_ok(module, action, iptype, cur_boxip):
# 	if not box_is_online(cur_boxip):
# 		print "box is not online, pls check"
# 		return False
	'''
		@module:USB/network/power;
		@action:USBState/closeusb/openusb;
			    netState/closenet/opennet;
				powerstate/closepower01/closepower01;
	'''
	for i in range(1,4):
		try:
			global exception_sleep
			time.sleep(exception_sleep)
			urllib_opener = urllib2.build_opener()
			urllib_opener.addheaders.append(('Cookie', 'jeesite.session.id=5666dc26a4b246f1b64ab1619da7c03f;\
			                                             Hm_lvt_82116c626a8d504a5c0675073362ef6f=1479692411,1481614969,1481764178,1481788301; \
														 token=493c7803bd33b8b05c823b9f87d62e1f; \
														 Hm_lpvt_82116c626a8d504a5c0675073362ef6f=1481790761; \
														 loginName=thinkgem;password=admin'))  
			url="http://localhost:8080/jeesite/test/%s/%s?%s=%s" % (module, action, iptype, cur_boxip)
			req = urllib2.Request(url)
			response = urllib_opener.open(req)
			retdata = response.read() 
			status = response.getcode()
			print '%s\ncode : %s , %s' %(action,status,retdata)
			if action == "closeusb":
				if not netBoxState(['00','02'], cur_boxip):
					print "close usb fail:%s" % i
				else:
					return True

			if action == "openusb":
				if not netBoxState(['01','03'], cur_boxip):
					print "open usb fail:%s" % i
				else:
					return True
			if action == "closenet":
				if not netBoxState(['00','01'], cur_boxip):
					print "close net fail:%s" % i
				else:
					return True
			if action == "opennet":
				if not netBoxState(['02','03'], cur_boxip):
					print "open net fail:%s" % i
				else:
					return True
				
			if action == "closepower01":
				if not netBoxState(['00','02'], cur_boxip, module="pwrBox"):
					print "close power01 fail:%s" % i
				else:
					return True	
			if action == "openpower01":
				if not netBoxState(['01','03'], cur_boxip, module="pwrBox"):
					print "open usb fail:%s" % i
				else:
					return True
			
			if i == 3:
				return False
			
		except HTTPError as e:
			if i <= 3:
				print "HTTPError action:%s, %s" % (action,str(e))
				exception_sleep = 10
				continue
			else:
				return False 
# 
# #for j in range(1, 100):
# while not ip_is_online("10.100.14.43"):
# 	#USB/network/power
# 	#print "*" * 15 + "第%s次尝试" % j + "*" * 15
# 	for index in module_index:
# 		cur_module = USB_NET_PW_INFO["module"][index]
# 		cur_actions = USB_NET_PW_INFO["actions"][index]
# 		cur_boxip  = USB_NET_PW_INFO["boxip"][index]
# 		cur_iptype = USB_NET_PW_INFO["iptype"][index]
# 		
# 		for cur_action in cur_actions:
# 			time.sleep(15)
# 			if not act_of_module_is_ok(cur_module, cur_action, cur_iptype, cur_boxip):
# 				print "========= operate %s fail =========" % cur_action
# 		print "========= operate %s done =========\n" % cur_module

if __name__=="__main__":
	try:
		print get_printer_info("192.168.103.207")
	except KeyError:
		for index in module_index:
	 		cur_module = USB_NET_PW_INFO["module"][index]
	 		cur_actions = USB_NET_PW_INFO["actions"][index]
	 		cur_boxip  = USB_NET_PW_INFO["boxip"][index]
	 		cur_iptype = USB_NET_PW_INFO["iptype"][index]
	 		
	 		for cur_action in cur_actions:
	 			time.sleep(15)
	 			if not act_of_module_is_ok(cur_module, cur_action, cur_iptype, cur_boxip):
	 				print "========= operate %s fail =========" % cur_action
	 		print "========= operate %s done =========\n" % cur_module
		